/*
 * Copyright 2008 Lucifer Lu
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using System;
using System.Collections.Generic;
using System.Windows.Browser;

namespace SilverChart.Core.Log {
    /// <summary>
    /// Description of Logger.
    /// </summary>
    public class Logger {
        private static Dictionary<String, Logger> _loggers;
        private static HtmlElement _logDiv;
        private static Logger _nullLogger;
        private static LogMessageFormater _formater;

        private String _loggerName;

        static Logger() {
            _loggers = new Dictionary<String, Logger>();
            _logDiv = null;
            _nullLogger = new Logger("__NULL_LOGGER__", new NullOutput());
            _formater = new DefaultLogMessageFormater();
        }

        public static Logger GetLogger<T>() {
            return GetLogger(typeof(T).FullName);
        }

        public static Logger GetLogger(String loggerName) {
            Logger logger = null;

#if DEBUG
            if (LoggerConfig != null && loggerName != null && loggerName.Trim().Length > 0) {
                String splitedLoggerName = loggerName;
                String matchName = splitedLoggerName;
                while (true) {
                    if (!_loggers.TryGetValue(matchName, out logger)) {
                        if (LoggerConfig.Loggers.Contains(matchName)) {
                            logger = new Logger(loggerName, new DefaultBrowserOutput(loggerName, _formater));
                            _loggers[loggerName] = logger;
                            break;
                        }
                        else {
                            Int32 lastNamespaceIndex = splitedLoggerName.LastIndexOf(".");
                            if (lastNamespaceIndex >= 0) {
                                splitedLoggerName = splitedLoggerName.Substring(0, lastNamespaceIndex);
                                matchName = splitedLoggerName + ".*";
                            }
                            else {
                                matchName = "*";
                            }
                        }
                    }
                    else {
                        break;
                    }
                }
            }
#endif
            if (logger == null) {
                logger = _nullLogger;
            }

            return logger;
        }

        public static void Initialize(LoggerConfigurations config) {
#if DEBUG
            LoggerConfig = config;
            if (LoggerConfig.DivName != null && LoggerConfig.DivName.Trim().Length > 0) {
                try {
                    OutputDiv = HtmlPage.Document.GetElementById(LoggerConfig.DivName);
                }
                catch {
                }
            }
            if (OutputDiv == null && LoggerConfig.CreateLogDiv) {
                try {
                    HtmlElement outerDiv = HtmlPage.Document.CreateElement("DIV");
                    outerDiv.SetStyleAttribute("width", "95%");
                    outerDiv.SetStyleAttribute("border", "solid black 1px");
                    HtmlPage.Document.Body.AppendChild(outerDiv);

                    HtmlElement headerDiv = HtmlPage.Document.CreateElement("DIV");
                    headerDiv.SetAttribute("id", "__logDivHeader");
                    headerDiv.SetStyleAttribute("backgroundColor", "Gray");
                    headerDiv.SetStyleAttribute("width", "100%");
                    headerDiv.SetAttribute("align", "center");
                    headerDiv.SetProperty("innerHTML", "Logger Window");
                    outerDiv.AppendChild(headerDiv);

                    OutputDiv = HtmlPage.Document.CreateElement("DIV");
                    OutputDiv.SetAttribute("id", "__logDiv");
                    OutputDiv.SetAttribute("align", "left");
                    OutputDiv.SetStyleAttribute("fontSize", "small");
                    OutputDiv.SetStyleAttribute("width", "100%");
                    outerDiv.AppendChild(OutputDiv);
                }
                catch {
                }
            }
#endif
        }

        private static LoggerConfigurations _loggerConfig;
        internal static LoggerConfigurations LoggerConfig {
            get {
                return _loggerConfig;
            }
            private set {
                _loggerConfig = value;
            }
        }

        internal static HtmlElement OutputDiv {
            get {
                return _logDiv;
            }
            private set {
                _logDiv = value;
            }
        }

        private Logger(String loggerName, LogOutput logOutput) {
            Output = logOutput;
            _loggerName = loggerName;
        }

        public String Name {
            get {
                return _loggerName;
            }
        }

        private LogOutput Output { get; set; }

        public void Debug(String log) {
#if DEBUG
            if (DebugLevel) {
                Exception e = new Exception();
                Output.debug(log, DateTime.Now, Name, 0);
            }
#endif
        }

        public void Info(String log) {
#if DEBUG
            if (InfoLevel) {
                Output.info(log, DateTime.Now, Name, 0);
            }
#endif
        }

        public void Warn(String log) {
#if DEBUG
            if (WarnLevel) {
                Output.warn(log, DateTime.Now, Name, 0, null);
            }
#endif
        }

        public Boolean DebugLevel {
            get {
#if DEBUG
                return LogLevel.Debug >= LoggerConfig.GlobalLogLevel;
#else
                return false;
#endif
            }
        }

        public Boolean InfoLevel {
            get {
#if DEBUG
                return LogLevel.Info >= LoggerConfig.GlobalLogLevel;
#else
                return false;
#endif
            }
        }

        public Boolean WarnLevel {
            get {
#if DEBUG
                return LogLevel.Warn >= LoggerConfig.GlobalLogLevel;
#else
                return false;
#endif
            }
        }


        public void Alert(String message) {
#if DEBUG
            Output.alert(message, Name, 0);
#endif
        }
    }
}
